/*
 * Copyright (c) 2025 Huawei Device, Inc. Ltd. and <马弓手>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SQLITE_PLUGIN_H
#define SQLITE_PLUGIN_H

#include "Thread.h"
#include "CordovaPlugin.h"
#include "cJSON.h"
#include "SQLiteConnectorDatabase.h"
#include <cstddef>
#include <map>
using namespace  std;
class SQLitePlugin:public CordovaPlugin {
    enum Action {
        echoStringValue,
        open,
        close,
        del,
        executeSqlBatch,
        backgroundExecuteSqlBatch,
    };
    struct DBQuery {
        bool m_stop;
        bool m_close;
        bool m_del;
        vector<string> m_queries;
        vector<cJSON*> m_jsonparams;
        CallbackContext m_cbc;
        
        DBQuery(vector<string> queries, vector<cJSON*> jsonparams, CallbackContext c) {
            m_stop = false;
            m_close = false;
            m_del = false;
            m_queries = queries;
            m_jsonparams = jsonparams;
            m_cbc = c;
        }
        
        DBQuery(bool del, CallbackContext cbc) {
            m_stop = false;
            m_close = false;
            m_del = del;
            m_cbc = cbc;
        }
        
        DBQuery() {
            m_stop = false;
            m_close = false;
            m_del = false;
        }
        ~DBQuery() {
            for(int i=0; i<m_jsonparams.size(); i++) {
                cJSON_Delete(m_jsonparams[i]);
            }
        }
        DBQuery(const DBQuery& arg) {
            m_stop = arg.m_stop;
            m_close = arg.m_close;
            m_del = arg.m_del;
            m_queries = arg.m_queries;
            m_jsonparams = arg.m_jsonparams;
            m_cbc = arg.m_cbc;
        }
        DBQuery& operator =(const DBQuery& arg) {
            if(this == &arg)
                return *this;
            m_stop = arg.m_stop;
            m_close = arg.m_close;
            m_del = arg.m_del;
            m_queries = arg.m_queries;
            m_jsonparams = arg.m_jsonparams;
            m_cbc = arg.m_cbc;
            return *this;
        }
    };
    class DBRunner : public CThreadPool{
        string m_dbName;
        public:
        SQliteConnectorDatabase m_mydb;
        
        DBRunner(string dbname) {
            m_dbName = dbname;
        }
        
        void Execute(const void* arg, const int nCountOfTask, void* pTmp=NULL) {
            DBQuery* dbq = (DBQuery*)arg;
            if(m_mydb.getSqlite() == NULL) {
                if(!m_mydb.open(m_dbName)) {
                    dbq->m_cbc.error("open database failed");
                }
            }
            
            if(!dbq->m_stop) {
                m_mydb.executeSqlBatch(dbq->m_queries, dbq->m_jsonparams, dbq->m_cbc);
            }
            if(dbq->m_close) {
                m_mydb.closeDatabaseNow();
                if(!dbq->m_del) {
                    dbq->m_cbc.success();
                } else {
                    m_mydb.deleteDatbaseNow();
                    dbq->m_cbc.success();
                }
            }
            delete dbq;
        }
        void* InitThreadData() {return NULL;}
	    void DeInitThreadData(void* pArg){}
    };
    map<string, DBRunner*>* m_dbrmap;
public:
    SQLitePlugin(){
        m_dbrmap = new map<string, DBRunner*>();
    }
    ~SQLitePlugin() {
        delete m_dbrmap;
    };
    bool execute(const string&  actionAsString, cJSON* args, CallbackContext cbc) override;
    bool executeAndPossiblyThrow(Action action, cJSON* args, CallbackContext cbc);
    void startDatabase(string dbname, cJSON* options, CallbackContext cbc);
    void closeDatabase(string dbname, CallbackContext cbc);
    void deleteDatabase(string dbname, CallbackContext cbc);
};
#endif